home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / tarfile.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  48KB  |  1,894 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. __version__ = '$Revision: 60730 $'
  5. version = '0.8.0'
  6. __author__ = 'Lars Gust\xe4bel (lars@gustaebel.de)'
  7. __date__ = '$Date: 2008-02-11 13:36:07 -0500 (Mon, 11 Feb 2008) $'
  8. __cvsid__ = '$Id: tarfile.py 60730 2008-02-11 18:36:07Z lars.gustaebel $'
  9. __credits__ = 'Gustavo Niemeyer, Niels Gust\xe4bel, Richard Townsend.'
  10. import sys
  11. import os
  12. import shutil
  13. import stat
  14. import errno
  15. import time
  16. import struct
  17. import copy
  18. if sys.platform == 'mac':
  19.     raise ImportError, 'tarfile does not work for platform==mac'
  20.  
  21.  
  22. try:
  23.     import grp
  24.     import pwd
  25. except ImportError:
  26.     grp = pwd = None
  27.  
  28. __all__ = [
  29.     'TarFile',
  30.     'TarInfo',
  31.     'is_tarfile',
  32.     'TarError']
  33. NUL = '\x00'
  34. BLOCKSIZE = 512
  35. RECORDSIZE = BLOCKSIZE * 20
  36. MAGIC = 'ustar'
  37. VERSION = '00'
  38. LENGTH_NAME = 100
  39. LENGTH_LINK = 100
  40. LENGTH_PREFIX = 155
  41. MAXSIZE_MEMBER = 0x1FFFFFFFFL
  42. REGTYPE = '0'
  43. AREGTYPE = '\x00'
  44. LNKTYPE = '1'
  45. SYMTYPE = '2'
  46. CHRTYPE = '3'
  47. BLKTYPE = '4'
  48. DIRTYPE = '5'
  49. FIFOTYPE = '6'
  50. CONTTYPE = '7'
  51. GNUTYPE_LONGNAME = 'L'
  52. GNUTYPE_LONGLINK = 'K'
  53. GNUTYPE_SPARSE = 'S'
  54. SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, GNUTYPE_SPARSE)
  55. REGULAR_TYPES = (REGTYPE, AREGTYPE, CONTTYPE, GNUTYPE_SPARSE)
  56. S_IFLNK = 40960
  57. S_IFREG = 32768
  58. S_IFBLK = 24576
  59. S_IFDIR = 16384
  60. S_IFCHR = 8192
  61. S_IFIFO = 4096
  62. TSUID = 2048
  63. TSGID = 1024
  64. TSVTX = 512
  65. TUREAD = 256
  66. TUWRITE = 128
  67. TUEXEC = 64
  68. TGREAD = 32
  69. TGWRITE = 16
  70. TGEXEC = 8
  71. TOREAD = 4
  72. TOWRITE = 2
  73. TOEXEC = 1
  74.  
  75. def stn(s, length):
  76.     return s[:length] + (length - len(s)) * NUL
  77.  
  78.  
  79. def nts(s):
  80.     p = s.find('\x00')
  81.     if p == -1:
  82.         return s
  83.     
  84.     return s[:p]
  85.  
  86.  
  87. def nti(s):
  88.     if s[0] != chr(128):
  89.         if not nts(s):
  90.             pass
  91.         n = int('0', 8)
  92.     else:
  93.         n = 0x0L
  94.         for i in xrange(len(s) - 1):
  95.             n <<= 8
  96.             n += ord(s[i + 1])
  97.         
  98.     return n
  99.  
  100.  
  101. def itn(n, digits = 8, posix = False):
  102.     if n <= n:
  103.         pass
  104.     elif n < 8 ** (digits - 1):
  105.         s = '%0*o' % (digits - 1, n) + NUL
  106.     elif posix:
  107.         raise ValueError('overflow in number field')
  108.     
  109.     if n < 0:
  110.         n = struct.unpack('L', struct.pack('l', n))[0]
  111.     
  112.     s = ''
  113.     for i in xrange(digits - 1):
  114.         s = chr(n & 255) + s
  115.         n >>= 8
  116.     
  117.     s = chr(128) + s
  118.     return s
  119.  
  120.  
  121. def calc_chksums(buf):
  122.     unsigned_chksum = 256 + sum(struct.unpack('148B', buf[:148]) + struct.unpack('356B', buf[156:512]))
  123.     signed_chksum = 256 + sum(struct.unpack('148b', buf[:148]) + struct.unpack('356b', buf[156:512]))
  124.     return (unsigned_chksum, signed_chksum)
  125.  
  126.  
  127. def copyfileobj(src, dst, length = None):
  128.     if length == 0:
  129.         return None
  130.     
  131.     if length is None:
  132.         shutil.copyfileobj(src, dst)
  133.         return None
  134.     
  135.     BUFSIZE = 16384
  136.     (blocks, remainder) = divmod(length, BUFSIZE)
  137.     for b in xrange(blocks):
  138.         buf = src.read(BUFSIZE)
  139.         if len(buf) < BUFSIZE:
  140.             raise IOError('end of file reached')
  141.         
  142.         dst.write(buf)
  143.     
  144.     if remainder != 0:
  145.         buf = src.read(remainder)
  146.         if len(buf) < remainder:
  147.             raise IOError('end of file reached')
  148.         
  149.         dst.write(buf)
  150.     
  151.  
  152. filemode_table = (((S_IFLNK, 'l'), (S_IFREG, '-'), (S_IFBLK, 'b'), (S_IFDIR, 'd'), (S_IFCHR, 'c'), (S_IFIFO, 'p')), ((TUREAD, 'r'),), ((TUWRITE, 'w'),), ((TUEXEC | TSUID, 's'), (TSUID, 'S'), (TUEXEC, 'x')), ((TGREAD, 'r'),), ((TGWRITE, 'w'),), ((TGEXEC | TSGID, 's'), (TSGID, 'S'), (TGEXEC, 'x')), ((TOREAD, 'r'),), ((TOWRITE, 'w'),), ((TOEXEC | TSVTX, 't'), (TSVTX, 'T'), (TOEXEC, 'x')))
  153.  
  154. def filemode(mode):
  155.     perm = []
  156.     for table in filemode_table:
  157.         for bit, char in table:
  158.             if mode & bit == bit:
  159.                 perm.append(char)
  160.                 break
  161.                 continue
  162.         
  163.     
  164.     return ''.join(perm)
  165.  
  166. if os.sep != '/':
  167.     
  168.     normpath = lambda path: os.path.normpath(path).replace(os.sep, '/')
  169. else:
  170.     normpath = os.path.normpath
  171.  
  172. class TarError(Exception):
  173.     pass
  174.  
  175.  
  176. class ExtractError(TarError):
  177.     pass
  178.  
  179.  
  180. class ReadError(TarError):
  181.     pass
  182.  
  183.  
  184. class CompressionError(TarError):
  185.     pass
  186.  
  187.  
  188. class StreamError(TarError):
  189.     pass
  190.  
  191.  
  192. class _LowLevelFile:
  193.     
  194.     def __init__(self, name, mode):
  195.         mode = {
  196.             'r': os.O_RDONLY,
  197.             'w': os.O_WRONLY | os.O_CREAT | os.O_TRUNC }[mode]
  198.         if hasattr(os, 'O_BINARY'):
  199.             mode |= os.O_BINARY
  200.         
  201.         self.fd = os.open(name, mode)
  202.  
  203.     
  204.     def close(self):
  205.         os.close(self.fd)
  206.  
  207.     
  208.     def read(self, size):
  209.         return os.read(self.fd, size)
  210.  
  211.     
  212.     def write(self, s):
  213.         os.write(self.fd, s)
  214.  
  215.  
  216.  
  217. class _Stream:
  218.     
  219.     def __init__(self, name, mode, comptype, fileobj, bufsize):
  220.         self._extfileobj = True
  221.         if fileobj is None:
  222.             fileobj = _LowLevelFile(name, mode)
  223.             self._extfileobj = False
  224.         
  225.         if comptype == '*':
  226.             fileobj = _StreamProxy(fileobj)
  227.             comptype = fileobj.getcomptype()
  228.         
  229.         if not name:
  230.             pass
  231.         self.name = ''
  232.         self.mode = mode
  233.         self.comptype = comptype
  234.         self.fileobj = fileobj
  235.         self.bufsize = bufsize
  236.         self.buf = ''
  237.         self.pos = 0x0L
  238.         self.closed = False
  239.         if comptype == 'gz':
  240.             
  241.             try:
  242.                 import zlib as zlib
  243.             except ImportError:
  244.                 raise CompressionError('zlib module is not available')
  245.  
  246.             self.zlib = zlib
  247.             self.crc = zlib.crc32('')
  248.             if mode == 'r':
  249.                 self._init_read_gz()
  250.             else:
  251.                 self._init_write_gz()
  252.         
  253.         if comptype == 'bz2':
  254.             
  255.             try:
  256.                 import bz2
  257.             except ImportError:
  258.                 raise CompressionError('bz2 module is not available')
  259.  
  260.             if mode == 'r':
  261.                 self.dbuf = ''
  262.                 self.cmp = bz2.BZ2Decompressor()
  263.             else:
  264.                 self.cmp = bz2.BZ2Compressor()
  265.         
  266.  
  267.     
  268.     def __del__(self):
  269.         if hasattr(self, 'closed') and not (self.closed):
  270.             self.close()
  271.         
  272.  
  273.     
  274.     def _init_write_gz(self):
  275.         self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, -(self.zlib.MAX_WBITS), self.zlib.DEF_MEM_LEVEL, 0)
  276.         timestamp = struct.pack('<L', long(time.time()))
  277.         self._Stream__write('\x1f\x8b\x08\x08%s\x02\xff' % timestamp)
  278.         if self.name.endswith('.gz'):
  279.             self.name = self.name[:-3]
  280.         
  281.         self._Stream__write(self.name + NUL)
  282.  
  283.     
  284.     def write(self, s):
  285.         if self.comptype == 'gz':
  286.             self.crc = self.zlib.crc32(s, self.crc)
  287.         
  288.         self.pos += len(s)
  289.         if self.comptype != 'tar':
  290.             s = self.cmp.compress(s)
  291.         
  292.         self._Stream__write(s)
  293.  
  294.     
  295.     def _Stream__write(self, s):
  296.         self.buf += s
  297.         while len(self.buf) > self.bufsize:
  298.             self.fileobj.write(self.buf[:self.bufsize])
  299.             self.buf = self.buf[self.bufsize:]
  300.             continue
  301.             self
  302.  
  303.     
  304.     def close(self):
  305.         if self.closed:
  306.             return None
  307.         
  308.         if self.mode == 'w' and self.comptype != 'tar':
  309.             self.buf += self.cmp.flush()
  310.         
  311.         if self.mode == 'w' and self.buf:
  312.             self.fileobj.write(self.buf)
  313.             self.buf = ''
  314.             if self.comptype == 'gz':
  315.                 self.fileobj.write(struct.pack('<L', self.crc & 0xFFFFFFFFL))
  316.                 self.fileobj.write(struct.pack('<L', self.pos & 0xFFFFFFFFL))
  317.             
  318.         
  319.         if not self._extfileobj:
  320.             self.fileobj.close()
  321.         
  322.         self.closed = True
  323.  
  324.     
  325.     def _init_read_gz(self):
  326.         self.cmp = self.zlib.decompressobj(-(self.zlib.MAX_WBITS))
  327.         self.dbuf = ''
  328.         if self._Stream__read(2) != '\x1f\x8b':
  329.             raise ReadError('not a gzip file')
  330.         
  331.         if self._Stream__read(1) != '\x08':
  332.             raise CompressionError('unsupported compression method')
  333.         
  334.         flag = ord(self._Stream__read(1))
  335.         self._Stream__read(6)
  336.         if flag & 4:
  337.             xlen = ord(self._Stream__read(1)) + 256 * ord(self._Stream__read(1))
  338.             self.read(xlen)
  339.         
  340.         if flag & 8:
  341.             while True:
  342.                 s = self._Stream__read(1)
  343.                 if not s or s == NUL:
  344.                     break
  345.                     continue
  346.         
  347.         if flag & 16:
  348.             while True:
  349.                 s = self._Stream__read(1)
  350.                 if not s or s == NUL:
  351.                     break
  352.                     continue
  353.         
  354.         if flag & 2:
  355.             self._Stream__read(2)
  356.         
  357.  
  358.     
  359.     def tell(self):
  360.         return self.pos
  361.  
  362.     
  363.     def seek(self, pos = 0):
  364.         if pos - self.pos >= 0:
  365.             (blocks, remainder) = divmod(pos - self.pos, self.bufsize)
  366.             for i in xrange(blocks):
  367.                 self.read(self.bufsize)
  368.             
  369.             self.read(remainder)
  370.         else:
  371.             raise StreamError('seeking backwards is not allowed')
  372.         return self.pos
  373.  
  374.     
  375.     def read(self, size = None):
  376.         if size is None:
  377.             t = []
  378.             while True:
  379.                 buf = self._read(self.bufsize)
  380.                 if not buf:
  381.                     break
  382.                 
  383.                 t.append(buf)
  384.             buf = ''.join(t)
  385.         else:
  386.             buf = self._read(size)
  387.         self.pos += len(buf)
  388.         return buf
  389.  
  390.     
  391.     def _read(self, size):
  392.         if self.comptype == 'tar':
  393.             return self._Stream__read(size)
  394.         
  395.         c = len(self.dbuf)
  396.         t = [
  397.             self.dbuf]
  398.         while c < size:
  399.             buf = self._Stream__read(self.bufsize)
  400.             if not buf:
  401.                 break
  402.             
  403.             buf = self.cmp.decompress(buf)
  404.             t.append(buf)
  405.             c += len(buf)
  406.         t = ''.join(t)
  407.         self.dbuf = t[size:]
  408.         return t[:size]
  409.  
  410.     
  411.     def _Stream__read(self, size):
  412.         c = len(self.buf)
  413.         t = [
  414.             self.buf]
  415.         while c < size:
  416.             buf = self.fileobj.read(self.bufsize)
  417.             if not buf:
  418.                 break
  419.             
  420.             t.append(buf)
  421.             c += len(buf)
  422.         t = ''.join(t)
  423.         self.buf = t[size:]
  424.         return t[:size]
  425.  
  426.  
  427.  
  428. class _StreamProxy(object):
  429.     
  430.     def __init__(self, fileobj):
  431.         self.fileobj = fileobj
  432.         self.buf = self.fileobj.read(BLOCKSIZE)
  433.  
  434.     
  435.     def read(self, size):
  436.         self.read = self.fileobj.read
  437.         return self.buf
  438.  
  439.     
  440.     def getcomptype(self):
  441.         if self.buf.startswith('\x1f\x8b\x08'):
  442.             return 'gz'
  443.         
  444.         if self.buf.startswith('BZh91'):
  445.             return 'bz2'
  446.         
  447.         return 'tar'
  448.  
  449.     
  450.     def close(self):
  451.         self.fileobj.close()
  452.  
  453.  
  454.  
  455. class _BZ2Proxy(object):
  456.     blocksize = 16384
  457.     
  458.     def __init__(self, fileobj, mode):
  459.         self.fileobj = fileobj
  460.         self.mode = mode
  461.         self.init()
  462.  
  463.     
  464.     def init(self):
  465.         import bz2
  466.         self.pos = 0
  467.         if self.mode == 'r':
  468.             self.bz2obj = bz2.BZ2Decompressor()
  469.             self.fileobj.seek(0)
  470.             self.buf = ''
  471.         else:
  472.             self.bz2obj = bz2.BZ2Compressor()
  473.  
  474.     
  475.     def read(self, size):
  476.         b = [
  477.             self.buf]
  478.         x = len(self.buf)
  479.         while x < size:
  480.             
  481.             try:
  482.                 raw = self.fileobj.read(self.blocksize)
  483.                 data = self.bz2obj.decompress(raw)
  484.                 b.append(data)
  485.             except EOFError:
  486.                 break
  487.  
  488.             x += len(data)
  489.         self.buf = ''.join(b)
  490.         buf = self.buf[:size]
  491.         self.buf = self.buf[size:]
  492.         self.pos += len(buf)
  493.         return buf
  494.  
  495.     
  496.     def seek(self, pos):
  497.         if pos < self.pos:
  498.             self.init()
  499.         
  500.         self.read(pos - self.pos)
  501.  
  502.     
  503.     def tell(self):
  504.         return self.pos
  505.  
  506.     
  507.     def write(self, data):
  508.         self.pos += len(data)
  509.         raw = self.bz2obj.compress(data)
  510.         self.fileobj.write(raw)
  511.  
  512.     
  513.     def close(self):
  514.         if self.mode == 'w':
  515.             raw = self.bz2obj.flush()
  516.             self.fileobj.write(raw)
  517.         
  518.         self.fileobj.close()
  519.  
  520.  
  521.  
  522. class _FileInFile(object):
  523.     
  524.     def __init__(self, fileobj, offset, size, sparse = None):
  525.         self.fileobj = fileobj
  526.         self.offset = offset
  527.         self.size = size
  528.         self.sparse = sparse
  529.         self.position = 0
  530.  
  531.     
  532.     def tell(self):
  533.         return self.position
  534.  
  535.     
  536.     def seek(self, position):
  537.         self.position = position
  538.  
  539.     
  540.     def read(self, size = None):
  541.         if size is None:
  542.             size = self.size - self.position
  543.         else:
  544.             size = min(size, self.size - self.position)
  545.         if self.sparse is None:
  546.             return self.readnormal(size)
  547.         else:
  548.             return self.readsparse(size)
  549.  
  550.     
  551.     def readnormal(self, size):
  552.         self.fileobj.seek(self.offset + self.position)
  553.         self.position += size
  554.         return self.fileobj.read(size)
  555.  
  556.     
  557.     def readsparse(self, size):
  558.         data = []
  559.         while size > 0:
  560.             buf = self.readsparsesection(size)
  561.             if not buf:
  562.                 break
  563.             
  564.             size -= len(buf)
  565.             data.append(buf)
  566.         return ''.join(data)
  567.  
  568.     
  569.     def readsparsesection(self, size):
  570.         section = self.sparse.find(self.position)
  571.         if section is None:
  572.             return ''
  573.         
  574.         size = min(size, section.offset + section.size - self.position)
  575.  
  576.  
  577.  
  578. class ExFileObject(object):
  579.     blocksize = 1024
  580.     
  581.     def __init__(self, tarfile, tarinfo):
  582.         self.fileobj = _FileInFile(tarfile.fileobj, tarinfo.offset_data, tarinfo.size, getattr(tarinfo, 'sparse', None))
  583.         self.name = tarinfo.name
  584.         self.mode = 'r'
  585.         self.closed = False
  586.         self.size = tarinfo.size
  587.         self.position = 0
  588.         self.buffer = ''
  589.  
  590.     
  591.     def read(self, size = None):
  592.         if self.closed:
  593.             raise ValueError('I/O operation on closed file')
  594.         
  595.         buf = ''
  596.         if self.buffer:
  597.             if size is None:
  598.                 buf = self.buffer
  599.                 self.buffer = ''
  600.             else:
  601.                 buf = self.buffer[:size]
  602.                 self.buffer = self.buffer[size:]
  603.         
  604.         if size is None:
  605.             buf += self.fileobj.read()
  606.         else:
  607.             buf += self.fileobj.read(size - len(buf))
  608.         self.position += len(buf)
  609.         return buf
  610.  
  611.     
  612.     def readline(self, size = -1):
  613.         if self.closed:
  614.             raise ValueError('I/O operation on closed file')
  615.         
  616.         if '\n' in self.buffer:
  617.             pos = self.buffer.find('\n') + 1
  618.         else:
  619.             buffers = [
  620.                 self.buffer]
  621.             while True:
  622.                 buf = self.fileobj.read(self.blocksize)
  623.                 buffers.append(buf)
  624.                 if not buf or '\n' in buf:
  625.                     self.buffer = ''.join(buffers)
  626.                     pos = self.buffer.find('\n') + 1
  627.                     if pos == 0:
  628.                         pos = len(self.buffer)
  629.                     
  630.                     break
  631.                     continue
  632.         if size != -1:
  633.             pos = min(size, pos)
  634.         
  635.         buf = self.buffer[:pos]
  636.         self.buffer = self.buffer[pos:]
  637.         self.position += len(buf)
  638.         return buf
  639.  
  640.     
  641.     def readlines(self):
  642.         result = []
  643.         while True:
  644.             line = self.readline()
  645.             if not line:
  646.                 break
  647.             
  648.             result.append(line)
  649.         return result
  650.  
  651.     
  652.     def tell(self):
  653.         if self.closed:
  654.             raise ValueError('I/O operation on closed file')
  655.         
  656.         return self.position
  657.  
  658.     
  659.     def seek(self, pos, whence = os.SEEK_SET):
  660.         if self.closed:
  661.             raise ValueError('I/O operation on closed file')
  662.         
  663.         if whence == os.SEEK_SET:
  664.             self.position = min(max(pos, 0), self.size)
  665.         elif whence == os.SEEK_CUR:
  666.             if pos < 0:
  667.                 self.position = max(self.position + pos, 0)
  668.             else:
  669.                 self.position = min(self.position + pos, self.size)
  670.         elif whence == os.SEEK_END:
  671.             self.position = max(min(self.size + pos, self.size), 0)
  672.         else:
  673.             raise ValueError('Invalid argument')
  674.         self.buffer = ''
  675.         self.fileobj.seek(self.position)
  676.  
  677.     
  678.     def close(self):
  679.         self.closed = True
  680.  
  681.     
  682.     def __iter__(self):
  683.         while True:
  684.             line = self.readline()
  685.             if not line:
  686.                 break
  687.             
  688.             yield line
  689.  
  690.  
  691.  
  692. class TarInfo(object):
  693.     
  694.     def __init__(self, name = ''):
  695.         self.name = name
  696.         self.mode = 438
  697.         self.uid = 0
  698.         self.gid = 0
  699.         self.size = 0
  700.         self.mtime = 0
  701.         self.chksum = 0
  702.         self.type = REGTYPE
  703.         self.linkname = ''
  704.         self.uname = 'user'
  705.         self.gname = 'group'
  706.         self.devmajor = 0
  707.         self.devminor = 0
  708.         self.offset = 0
  709.         self.offset_data = 0
  710.  
  711.     
  712.     def __repr__(self):
  713.         return '<%s %r at %#x>' % (self.__class__.__name__, self.name, id(self))
  714.  
  715.     
  716.     def frombuf(cls, buf):
  717.         if len(buf) != BLOCKSIZE:
  718.             raise ValueError('truncated header')
  719.         
  720.         if buf.count(NUL) == BLOCKSIZE:
  721.             raise ValueError('empty header')
  722.         
  723.         tarinfo = cls()
  724.         tarinfo.buf = buf
  725.         tarinfo.name = nts(buf[0:100])
  726.         tarinfo.mode = nti(buf[100:108])
  727.         tarinfo.uid = nti(buf[108:116])
  728.         tarinfo.gid = nti(buf[116:124])
  729.         tarinfo.size = nti(buf[124:136])
  730.         tarinfo.mtime = nti(buf[136:148])
  731.         tarinfo.chksum = nti(buf[148:156])
  732.         tarinfo.type = buf[156:157]
  733.         tarinfo.linkname = nts(buf[157:257])
  734.         tarinfo.uname = nts(buf[265:297])
  735.         tarinfo.gname = nts(buf[297:329])
  736.         tarinfo.devmajor = nti(buf[329:337])
  737.         tarinfo.devminor = nti(buf[337:345])
  738.         prefix = nts(buf[345:500])
  739.         if prefix and not tarinfo.issparse():
  740.             tarinfo.name = prefix + '/' + tarinfo.name
  741.         
  742.         if tarinfo.chksum not in calc_chksums(buf):
  743.             raise ValueError('invalid header')
  744.         
  745.         return tarinfo
  746.  
  747.     frombuf = classmethod(frombuf)
  748.     
  749.     def tobuf(self, posix = False):
  750.         buf = ''
  751.         type = self.type
  752.         prefix = ''
  753.         if self.name.endswith('/'):
  754.             type = DIRTYPE
  755.         
  756.         if type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
  757.             name = self.name
  758.         else:
  759.             name = normpath(self.name)
  760.         if type == DIRTYPE:
  761.             name += '/'
  762.         
  763.         linkname = self.linkname
  764.         if linkname:
  765.             linkname = normpath(linkname)
  766.         
  767.         if posix:
  768.             if self.size > MAXSIZE_MEMBER:
  769.                 raise ValueError('file is too large (>= 8 GB)')
  770.             
  771.             if len(self.linkname) > LENGTH_LINK:
  772.                 raise ValueError('linkname is too long (>%d)' % LENGTH_LINK)
  773.             
  774.             if len(name) > LENGTH_NAME:
  775.                 prefix = name[:LENGTH_PREFIX + 1]
  776.                 while prefix and prefix[-1] != '/':
  777.                     prefix = prefix[:-1]
  778.                 name = name[len(prefix):]
  779.                 prefix = prefix[:-1]
  780.                 if not prefix or len(name) > LENGTH_NAME:
  781.                     raise ValueError('name is too long')
  782.                 
  783.             
  784.         elif len(self.linkname) > LENGTH_LINK:
  785.             buf += self._create_gnulong(self.linkname, GNUTYPE_LONGLINK)
  786.         
  787.         if len(name) > LENGTH_NAME:
  788.             buf += self._create_gnulong(name, GNUTYPE_LONGNAME)
  789.         
  790.         parts = [
  791.             stn(name, 100),
  792.             itn(self.mode & 4095, 8, posix),
  793.             itn(self.uid, 8, posix),
  794.             itn(self.gid, 8, posix),
  795.             itn(self.size, 12, posix),
  796.             itn(self.mtime, 12, posix),
  797.             '        ',
  798.             type,
  799.             stn(self.linkname, 100),
  800.             stn(MAGIC, 6),
  801.             stn(VERSION, 2),
  802.             stn(self.uname, 32),
  803.             stn(self.gname, 32),
  804.             itn(self.devmajor, 8, posix),
  805.             itn(self.devminor, 8, posix),
  806.             stn(prefix, 155)]
  807.         buf += ''.join(parts).ljust(BLOCKSIZE, NUL)
  808.         chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
  809.         buf = buf[:-364] + '%06o\x00' % chksum + buf[-357:]
  810.         self.buf = buf
  811.         return buf
  812.  
  813.     
  814.     def _create_gnulong(self, name, type):
  815.         name += NUL
  816.         tarinfo = self.__class__()
  817.         tarinfo.name = '././@LongLink'
  818.         tarinfo.type = type
  819.         tarinfo.mode = 0
  820.         tarinfo.size = len(name)
  821.         buf = tarinfo.tobuf()
  822.         buf += name
  823.         (blocks, remainder) = divmod(len(name), BLOCKSIZE)
  824.         if remainder > 0:
  825.             buf += (BLOCKSIZE - remainder) * NUL
  826.         
  827.         return buf
  828.  
  829.     
  830.     def isreg(self):
  831.         return self.type in REGULAR_TYPES
  832.  
  833.     
  834.     def isfile(self):
  835.         return self.isreg()
  836.  
  837.     
  838.     def isdir(self):
  839.         return self.type == DIRTYPE
  840.  
  841.     
  842.     def issym(self):
  843.         return self.type == SYMTYPE
  844.  
  845.     
  846.     def islnk(self):
  847.         return self.type == LNKTYPE
  848.  
  849.     
  850.     def ischr(self):
  851.         return self.type == CHRTYPE
  852.  
  853.     
  854.     def isblk(self):
  855.         return self.type == BLKTYPE
  856.  
  857.     
  858.     def isfifo(self):
  859.         return self.type == FIFOTYPE
  860.  
  861.     
  862.     def issparse(self):
  863.         return self.type == GNUTYPE_SPARSE
  864.  
  865.     
  866.     def isdev(self):
  867.         return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
  868.  
  869.  
  870.  
  871. class TarFile(object):
  872.     debug = 0
  873.     dereference = False
  874.     ignore_zeros = False
  875.     errorlevel = 0
  876.     posix = False
  877.     fileobject = ExFileObject
  878.     
  879.     def __init__(self, name = None, mode = 'r', fileobj = None):
  880.         if len(mode) > 1 or mode not in 'raw':
  881.             raise ValueError("mode must be 'r', 'a' or 'w'")
  882.         
  883.         self._mode = mode
  884.         self.mode = {
  885.             'r': 'rb',
  886.             'a': 'r+b',
  887.             'w': 'wb' }[mode]
  888.         if not fileobj:
  889.             fileobj = file(name, self.mode)
  890.             self._extfileobj = False
  891.         elif name is None and hasattr(fileobj, 'name'):
  892.             name = fileobj.name
  893.         
  894.         if hasattr(fileobj, 'mode'):
  895.             self.mode = fileobj.mode
  896.         
  897.         self._extfileobj = True
  898.         self.name = None if name else None
  899.         self.fileobj = fileobj
  900.         self.closed = False
  901.         self.members = []
  902.         self._loaded = False
  903.         self.offset = self.fileobj.tell()
  904.         self.inodes = { }
  905.         if self._mode == 'r':
  906.             self.firstmember = None
  907.             self.firstmember = self.next()
  908.         
  909.         if self._mode == 'a':
  910.             self.firstmember = None
  911.             while True:
  912.                 
  913.                 try:
  914.                     tarinfo = self.next()
  915.                 except ReadError:
  916.                     self.fileobj.seek(0)
  917.                     break
  918.  
  919.                 if tarinfo is None:
  920.                     self.fileobj.seek(-BLOCKSIZE, 1)
  921.                     break
  922.                     continue
  923.         
  924.         if self._mode in 'aw':
  925.             self._loaded = True
  926.         
  927.  
  928.     
  929.     def open(cls, name = None, mode = 'r', fileobj = None, bufsize = 10240):
  930.         if not name and not fileobj:
  931.             raise ValueError('nothing to open')
  932.         
  933.         if mode in ('r', 'r:*'):
  934.             for comptype in cls.OPEN_METH:
  935.                 func = getattr(cls, cls.OPEN_METH[comptype])
  936.                 if fileobj is not None:
  937.                     saved_pos = fileobj.tell()
  938.                 
  939.                 
  940.                 try:
  941.                     return func(name, 'r', fileobj)
  942.                 continue
  943.                 except (ReadError, CompressionError):
  944.                     if fileobj is not None:
  945.                         fileobj.seek(saved_pos)
  946.                         continue
  947.                     continue
  948.                     continue
  949.                 
  950.  
  951.             
  952.             raise ReadError('file could not be opened successfully')
  953.         elif ':' in mode:
  954.             (filemode, comptype) = mode.split(':', 1)
  955.             if not filemode:
  956.                 pass
  957.             filemode = 'r'
  958.             if not comptype:
  959.                 pass
  960.             comptype = 'tar'
  961.             if comptype in cls.OPEN_METH:
  962.                 func = getattr(cls, cls.OPEN_METH[comptype])
  963.             else:
  964.                 raise CompressionError('unknown compression type %r' % comptype)
  965.             return func(name, filemode, fileobj)
  966.         elif '|' in mode:
  967.             (filemode, comptype) = mode.split('|', 1)
  968.             if not filemode:
  969.                 pass
  970.             filemode = 'r'
  971.             if not comptype:
  972.                 pass
  973.             comptype = 'tar'
  974.             if filemode not in 'rw':
  975.                 raise ValueError("mode must be 'r' or 'w'")
  976.             
  977.             t = cls(name, filemode, _Stream(name, filemode, comptype, fileobj, bufsize))
  978.             t._extfileobj = False
  979.             return t
  980.         elif mode in 'aw':
  981.             return cls.taropen(name, mode, fileobj)
  982.         
  983.         raise ValueError('undiscernible mode')
  984.  
  985.     open = classmethod(open)
  986.     
  987.     def taropen(cls, name, mode = 'r', fileobj = None):
  988.         if len(mode) > 1 or mode not in 'raw':
  989.             raise ValueError("mode must be 'r', 'a' or 'w'")
  990.         
  991.         return cls(name, mode, fileobj)
  992.  
  993.     taropen = classmethod(taropen)
  994.     
  995.     def gzopen(cls, name, mode = 'r', fileobj = None, compresslevel = 9):
  996.         if len(mode) > 1 or mode not in 'rw':
  997.             raise ValueError("mode must be 'r' or 'w'")
  998.         
  999.         
  1000.         try:
  1001.             import gzip as gzip
  1002.             gzip.GzipFile
  1003.         except (ImportError, AttributeError):
  1004.             raise CompressionError('gzip module is not available')
  1005.  
  1006.         if fileobj is None:
  1007.             fileobj = file(name, mode + 'b')
  1008.         
  1009.         
  1010.         try:
  1011.             t = cls.taropen(name, mode, gzip.GzipFile(name, mode, compresslevel, fileobj))
  1012.         except IOError:
  1013.             raise ReadError('not a gzip file')
  1014.  
  1015.         t._extfileobj = False
  1016.         return t
  1017.  
  1018.     gzopen = classmethod(gzopen)
  1019.     
  1020.     def bz2open(cls, name, mode = 'r', fileobj = None, compresslevel = 9):
  1021.         if len(mode) > 1 or mode not in 'rw':
  1022.             raise ValueError("mode must be 'r' or 'w'.")
  1023.         
  1024.         
  1025.         try:
  1026.             import bz2
  1027.         except ImportError:
  1028.             raise CompressionError('bz2 module is not available')
  1029.  
  1030.         if fileobj is not None:
  1031.             fileobj = _BZ2Proxy(fileobj, mode)
  1032.         else:
  1033.             fileobj = bz2.BZ2File(name, mode, compresslevel = compresslevel)
  1034.         
  1035.         try:
  1036.             t = cls.taropen(name, mode, fileobj)
  1037.         except IOError:
  1038.             raise ReadError('not a bzip2 file')
  1039.  
  1040.         t._extfileobj = False
  1041.         return t
  1042.  
  1043.     bz2open = classmethod(bz2open)
  1044.     OPEN_METH = {
  1045.         'tar': 'taropen',
  1046.         'gz': 'gzopen',
  1047.         'bz2': 'bz2open' }
  1048.     
  1049.     def close(self):
  1050.         if self.closed:
  1051.             return None
  1052.         
  1053.         if self._mode in 'aw':
  1054.             self.fileobj.write(NUL * BLOCKSIZE * 2)
  1055.             self.offset += BLOCKSIZE * 2
  1056.             (blocks, remainder) = divmod(self.offset, RECORDSIZE)
  1057.             if remainder > 0:
  1058.                 self.fileobj.write(NUL * (RECORDSIZE - remainder))
  1059.             
  1060.         
  1061.         if not self._extfileobj:
  1062.             self.fileobj.close()
  1063.         
  1064.         self.closed = True
  1065.  
  1066.     
  1067.     def getmember(self, name):
  1068.         tarinfo = self._getmember(name)
  1069.         if tarinfo is None:
  1070.             raise KeyError('filename %r not found' % name)
  1071.         
  1072.         return tarinfo
  1073.  
  1074.     
  1075.     def getmembers(self):
  1076.         self._check()
  1077.         if not self._loaded:
  1078.             self._load()
  1079.         
  1080.         return self.members
  1081.  
  1082.     
  1083.     def getnames(self):
  1084.         return [ tarinfo.name for tarinfo in self.getmembers() ]
  1085.  
  1086.     
  1087.     def gettarinfo(self, name = None, arcname = None, fileobj = None):
  1088.         self._check('aw')
  1089.         if fileobj is not None:
  1090.             name = fileobj.name
  1091.         
  1092.         if arcname is None:
  1093.             arcname = name
  1094.         
  1095.         arcname = normpath(arcname)
  1096.         (drv, arcname) = os.path.splitdrive(arcname)
  1097.         while arcname[0:1] == '/':
  1098.             arcname = arcname[1:]
  1099.         tarinfo = TarInfo()
  1100.         if fileobj is None:
  1101.             if hasattr(os, 'lstat') and not (self.dereference):
  1102.                 statres = os.lstat(name)
  1103.             else:
  1104.                 statres = os.stat(name)
  1105.         else:
  1106.             statres = os.fstat(fileobj.fileno())
  1107.         linkname = ''
  1108.         stmd = statres.st_mode
  1109.         if stat.S_ISREG(stmd):
  1110.             inode = (statres.st_ino, statres.st_dev)
  1111.             if not (self.dereference) and statres.st_nlink > 1 and inode in self.inodes:
  1112.                 type = LNKTYPE
  1113.                 linkname = self.inodes[inode]
  1114.             else:
  1115.                 type = REGTYPE
  1116.                 if inode[0]:
  1117.                     self.inodes[inode] = arcname
  1118.                 
  1119.         elif stat.S_ISDIR(stmd):
  1120.             type = DIRTYPE
  1121.             if arcname[-1:] != '/':
  1122.                 arcname += '/'
  1123.             
  1124.         elif stat.S_ISFIFO(stmd):
  1125.             type = FIFOTYPE
  1126.         elif stat.S_ISLNK(stmd):
  1127.             type = SYMTYPE
  1128.             linkname = os.readlink(name)
  1129.         elif stat.S_ISCHR(stmd):
  1130.             type = CHRTYPE
  1131.         elif stat.S_ISBLK(stmd):
  1132.             type = BLKTYPE
  1133.         else:
  1134.             return None
  1135.         tarinfo.name = arcname
  1136.         tarinfo.mode = stmd
  1137.         tarinfo.uid = statres.st_uid
  1138.         tarinfo.gid = statres.st_gid
  1139.         if stat.S_ISREG(stmd):
  1140.             tarinfo.size = statres.st_size
  1141.         else:
  1142.             tarinfo.size = 0x0L
  1143.         tarinfo.mtime = statres.st_mtime
  1144.         tarinfo.type = type
  1145.         tarinfo.linkname = linkname
  1146.         if pwd:
  1147.             
  1148.             try:
  1149.                 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
  1150.             except KeyError:
  1151.                 pass
  1152.             except:
  1153.                 None<EXCEPTION MATCH>KeyError
  1154.             
  1155.  
  1156.         None<EXCEPTION MATCH>KeyError
  1157.         if grp:
  1158.             
  1159.             try:
  1160.                 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
  1161.             except KeyError:
  1162.                 pass
  1163.             except:
  1164.                 None<EXCEPTION MATCH>KeyError
  1165.             
  1166.  
  1167.         None<EXCEPTION MATCH>KeyError
  1168.         if type in (CHRTYPE, BLKTYPE):
  1169.             if hasattr(os, 'major') and hasattr(os, 'minor'):
  1170.                 tarinfo.devmajor = os.major(statres.st_rdev)
  1171.                 tarinfo.devminor = os.minor(statres.st_rdev)
  1172.             
  1173.         
  1174.         return tarinfo
  1175.  
  1176.     
  1177.     def list(self, verbose = True):
  1178.         self._check()
  1179.         for tarinfo in self:
  1180.             if verbose:
  1181.                 print filemode(tarinfo.mode), None % ('%s/%s', tarinfo.uid if not tarinfo.uname else tarinfo.gid),
  1182.                 if tarinfo.ischr() or tarinfo.isblk():
  1183.                     print '%10s' % '%d,%d' % (tarinfo.devmajor, tarinfo.devminor),
  1184.                 else:
  1185.                     print '%10d' % tarinfo.size,
  1186.                 print '%d-%02d-%02d %02d:%02d:%02d' % time.localtime(tarinfo.mtime)[:6],
  1187.             
  1188.             print tarinfo.name,
  1189.             if verbose:
  1190.                 if tarinfo.issym():
  1191.                     print '->', tarinfo.linkname,
  1192.                 
  1193.                 if tarinfo.islnk():
  1194.                     print 'link to', tarinfo.linkname,
  1195.                 
  1196.             
  1197.             print 
  1198.         
  1199.  
  1200.     
  1201.     def add(self, name, arcname = None, recursive = True):
  1202.         self._check('aw')
  1203.         if arcname is None:
  1204.             arcname = name
  1205.         
  1206.         if self.name is not None and os.path.abspath(name) == self.name:
  1207.             self._dbg(2, 'tarfile: Skipped %r' % name)
  1208.             return None
  1209.         
  1210.         if name == '.':
  1211.             if recursive:
  1212.                 if arcname == '.':
  1213.                     arcname = ''
  1214.                 
  1215.                 for f in os.listdir('.'):
  1216.                     self.add(f, os.path.join(arcname, f))
  1217.                 
  1218.             
  1219.             return None
  1220.         
  1221.         self._dbg(1, name)
  1222.         tarinfo = self.gettarinfo(name, arcname)
  1223.         if tarinfo is None:
  1224.             self._dbg(1, 'tarfile: Unsupported type %r' % name)
  1225.             return None
  1226.         
  1227.         if tarinfo.isreg():
  1228.             f = file(name, 'rb')
  1229.             self.addfile(tarinfo, f)
  1230.             f.close()
  1231.         elif tarinfo.isdir():
  1232.             self.addfile(tarinfo)
  1233.             if recursive:
  1234.                 for f in os.listdir(name):
  1235.                     self.add(os.path.join(name, f), os.path.join(arcname, f))
  1236.                 
  1237.             
  1238.         else:
  1239.             self.addfile(tarinfo)
  1240.  
  1241.     
  1242.     def addfile(self, tarinfo, fileobj = None):
  1243.         self._check('aw')
  1244.         tarinfo = copy.copy(tarinfo)
  1245.         buf = tarinfo.tobuf(self.posix)
  1246.         self.fileobj.write(buf)
  1247.         self.offset += len(buf)
  1248.         if fileobj is not None:
  1249.             copyfileobj(fileobj, self.fileobj, tarinfo.size)
  1250.             (blocks, remainder) = divmod(tarinfo.size, BLOCKSIZE)
  1251.             if remainder > 0:
  1252.                 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
  1253.                 blocks += 1
  1254.             
  1255.             self.offset += blocks * BLOCKSIZE
  1256.         
  1257.         self.members.append(tarinfo)
  1258.  
  1259.     
  1260.     def extractall(self, path = '.', members = None):
  1261.         directories = []
  1262.         if members is None:
  1263.             members = self
  1264.         
  1265.         for tarinfo in members:
  1266.             if tarinfo.isdir():
  1267.                 directories.append(tarinfo)
  1268.                 tarinfo = copy.copy(tarinfo)
  1269.                 tarinfo.mode = 448
  1270.             
  1271.             self.extract(tarinfo, path)
  1272.         
  1273.         directories.sort((lambda a, b: cmp(a.name, b.name)))
  1274.         directories.reverse()
  1275.         for tarinfo in directories:
  1276.             dirpath = os.path.join(path, tarinfo.name)
  1277.             
  1278.             try:
  1279.                 self.chown(tarinfo, dirpath)
  1280.                 self.utime(tarinfo, dirpath)
  1281.                 self.chmod(tarinfo, dirpath)
  1282.             continue
  1283.             except ExtractError:
  1284.                 e = None
  1285.                 if self.errorlevel > 1:
  1286.                     raise 
  1287.                 else:
  1288.                     self._dbg(1, 'tarfile: %s' % e)
  1289.                 self.errorlevel > 1
  1290.             
  1291.  
  1292.         
  1293.  
  1294.     
  1295.     def extract(self, member, path = ''):
  1296.         self._check('r')
  1297.         if isinstance(member, TarInfo):
  1298.             tarinfo = member
  1299.         else:
  1300.             tarinfo = self.getmember(member)
  1301.         if tarinfo.islnk():
  1302.             tarinfo._link_target = os.path.join(path, tarinfo.linkname)
  1303.         
  1304.         
  1305.         try:
  1306.             self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
  1307.         except EnvironmentError:
  1308.             e = None
  1309.             if self.errorlevel > 0:
  1310.                 raise 
  1311.             elif e.filename is None:
  1312.                 self._dbg(1, 'tarfile: %s' % e.strerror)
  1313.             else:
  1314.                 self._dbg(1, 'tarfile: %s %r' % (e.strerror, e.filename))
  1315.         except ExtractError:
  1316.             e = None
  1317.             if self.errorlevel > 1:
  1318.                 raise 
  1319.             else:
  1320.                 self._dbg(1, 'tarfile: %s' % e)
  1321.         except:
  1322.             self.errorlevel > 1
  1323.  
  1324.  
  1325.     
  1326.     def extractfile(self, member):
  1327.         self._check('r')
  1328.         if isinstance(member, TarInfo):
  1329.             tarinfo = member
  1330.         else:
  1331.             tarinfo = self.getmember(member)
  1332.         if tarinfo.isreg():
  1333.             return self.fileobject(self, tarinfo)
  1334.         elif tarinfo.type not in SUPPORTED_TYPES:
  1335.             return self.fileobject(self, tarinfo)
  1336.         elif tarinfo.islnk() or tarinfo.issym():
  1337.             if isinstance(self.fileobj, _Stream):
  1338.                 raise StreamError('cannot extract (sym)link as file object')
  1339.             else:
  1340.                 return self.extractfile(self._getmember(tarinfo.linkname, tarinfo))
  1341.         else:
  1342.             return None
  1343.  
  1344.     
  1345.     def _extract_member(self, tarinfo, targetpath):
  1346.         if targetpath[-1:] == '/':
  1347.             targetpath = targetpath[:-1]
  1348.         
  1349.         targetpath = os.path.normpath(targetpath)
  1350.         upperdirs = os.path.dirname(targetpath)
  1351.         if upperdirs and not os.path.exists(upperdirs):
  1352.             os.makedirs(upperdirs)
  1353.         
  1354.         if tarinfo.islnk() or tarinfo.issym():
  1355.             self._dbg(1, '%s -> %s' % (tarinfo.name, tarinfo.linkname))
  1356.         else:
  1357.             self._dbg(1, tarinfo.name)
  1358.         if tarinfo.isreg():
  1359.             self.makefile(tarinfo, targetpath)
  1360.         elif tarinfo.isdir():
  1361.             self.makedir(tarinfo, targetpath)
  1362.         elif tarinfo.isfifo():
  1363.             self.makefifo(tarinfo, targetpath)
  1364.         elif tarinfo.ischr() or tarinfo.isblk():
  1365.             self.makedev(tarinfo, targetpath)
  1366.         elif tarinfo.islnk() or tarinfo.issym():
  1367.             self.makelink(tarinfo, targetpath)
  1368.         elif tarinfo.type not in SUPPORTED_TYPES:
  1369.             self.makeunknown(tarinfo, targetpath)
  1370.         else:
  1371.             self.makefile(tarinfo, targetpath)
  1372.         self.chown(tarinfo, targetpath)
  1373.         if not tarinfo.issym():
  1374.             self.chmod(tarinfo, targetpath)
  1375.             self.utime(tarinfo, targetpath)
  1376.         
  1377.  
  1378.     
  1379.     def makedir(self, tarinfo, targetpath):
  1380.         
  1381.         try:
  1382.             os.mkdir(targetpath, 448)
  1383.         except EnvironmentError:
  1384.             e = None
  1385.             if e.errno != errno.EEXIST:
  1386.                 raise 
  1387.             
  1388.         except:
  1389.             e.errno != errno.EEXIST
  1390.  
  1391.  
  1392.     
  1393.     def makefile(self, tarinfo, targetpath):
  1394.         source = self.extractfile(tarinfo)
  1395.         target = file(targetpath, 'wb')
  1396.         copyfileobj(source, target)
  1397.         source.close()
  1398.         target.close()
  1399.  
  1400.     
  1401.     def makeunknown(self, tarinfo, targetpath):
  1402.         self.makefile(tarinfo, targetpath)
  1403.         self._dbg(1, 'tarfile: Unknown file type %r, extracted as regular file.' % tarinfo.type)
  1404.  
  1405.     
  1406.     def makefifo(self, tarinfo, targetpath):
  1407.         if hasattr(os, 'mkfifo'):
  1408.             os.mkfifo(targetpath)
  1409.         else:
  1410.             raise ExtractError('fifo not supported by system')
  1411.  
  1412.     
  1413.     def makedev(self, tarinfo, targetpath):
  1414.         if not hasattr(os, 'mknod') or not hasattr(os, 'makedev'):
  1415.             raise ExtractError('special devices not supported by system')
  1416.         
  1417.         mode = tarinfo.mode
  1418.         if tarinfo.isblk():
  1419.             mode |= stat.S_IFBLK
  1420.         else:
  1421.             mode |= stat.S_IFCHR
  1422.         os.mknod(targetpath, mode, os.makedev(tarinfo.devmajor, tarinfo.devminor))
  1423.  
  1424.     
  1425.     def makelink(self, tarinfo, targetpath):
  1426.         linkpath = tarinfo.linkname
  1427.         
  1428.         try:
  1429.             if tarinfo.issym():
  1430.                 os.symlink(linkpath, targetpath)
  1431.             else:
  1432.                 os.link(tarinfo._link_target, targetpath)
  1433.         except AttributeError:
  1434.             if tarinfo.issym():
  1435.                 linkpath = os.path.join(os.path.dirname(tarinfo.name), linkpath)
  1436.                 linkpath = normpath(linkpath)
  1437.             
  1438.             
  1439.             try:
  1440.                 self._extract_member(self.getmember(linkpath), targetpath)
  1441.             except (EnvironmentError, KeyError):
  1442.                 e = None
  1443.                 linkpath = os.path.normpath(linkpath)
  1444.                 
  1445.                 try:
  1446.                     shutil.copy2(linkpath, targetpath)
  1447.                 except EnvironmentError:
  1448.                     e = None
  1449.                     raise IOError('link could not be created')
  1450.                 except:
  1451.                     None<EXCEPTION MATCH>EnvironmentError
  1452.                 
  1453.  
  1454.                 None<EXCEPTION MATCH>EnvironmentError
  1455.             
  1456.  
  1457.             None<EXCEPTION MATCH>(EnvironmentError, KeyError)
  1458.  
  1459.  
  1460.     
  1461.     def chown(self, tarinfo, targetpath):
  1462.         if pwd and hasattr(os, 'geteuid') and os.geteuid() == 0:
  1463.             
  1464.             try:
  1465.                 g = grp.getgrnam(tarinfo.gname)[2]
  1466.             except KeyError:
  1467.                 
  1468.                 try:
  1469.                     g = grp.getgrgid(tarinfo.gid)[2]
  1470.                 except KeyError:
  1471.                     g = os.getgid()
  1472.                 except:
  1473.                     None<EXCEPTION MATCH>KeyError
  1474.                 
  1475.  
  1476.                 None<EXCEPTION MATCH>KeyError
  1477.  
  1478.             
  1479.             try:
  1480.                 u = pwd.getpwnam(tarinfo.uname)[2]
  1481.             except KeyError:
  1482.                 
  1483.                 try:
  1484.                     u = pwd.getpwuid(tarinfo.uid)[2]
  1485.                 except KeyError:
  1486.                     u = os.getuid()
  1487.                 except:
  1488.                     None<EXCEPTION MATCH>KeyError
  1489.                 
  1490.  
  1491.                 None<EXCEPTION MATCH>KeyError
  1492.  
  1493.             
  1494.             try:
  1495.                 if tarinfo.issym() and hasattr(os, 'lchown'):
  1496.                     os.lchown(targetpath, u, g)
  1497.                 elif sys.platform != 'os2emx':
  1498.                     os.chown(targetpath, u, g)
  1499.             except EnvironmentError:
  1500.                 e = None
  1501.                 raise ExtractError('could not change owner')
  1502.             except:
  1503.                 None<EXCEPTION MATCH>EnvironmentError
  1504.             
  1505.  
  1506.         None<EXCEPTION MATCH>EnvironmentError
  1507.  
  1508.     
  1509.     def chmod(self, tarinfo, targetpath):
  1510.         if hasattr(os, 'chmod'):
  1511.             
  1512.             try:
  1513.                 os.chmod(targetpath, tarinfo.mode)
  1514.             except EnvironmentError:
  1515.                 e = None
  1516.                 raise ExtractError('could not change mode')
  1517.             except:
  1518.                 None<EXCEPTION MATCH>EnvironmentError
  1519.             
  1520.  
  1521.         None<EXCEPTION MATCH>EnvironmentError
  1522.  
  1523.     
  1524.     def utime(self, tarinfo, targetpath):
  1525.         if not hasattr(os, 'utime'):
  1526.             return None
  1527.         
  1528.         if sys.platform == 'win32' and tarinfo.isdir():
  1529.             return None
  1530.         
  1531.         
  1532.         try:
  1533.             os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
  1534.         except EnvironmentError:
  1535.             e = None
  1536.             raise ExtractError('could not change modification time')
  1537.  
  1538.  
  1539.     
  1540.     def next(self):
  1541.         self._check('ra')
  1542.         if self.firstmember is not None:
  1543.             m = self.firstmember
  1544.             self.firstmember = None
  1545.             return m
  1546.         
  1547.         self.fileobj.seek(self.offset)
  1548.         while True:
  1549.             buf = self.fileobj.read(BLOCKSIZE)
  1550.             if not buf:
  1551.                 return None
  1552.             
  1553.             
  1554.             try:
  1555.                 tarinfo = TarInfo.frombuf(buf)
  1556.                 tarinfo.offset = self.offset
  1557.                 self.offset += BLOCKSIZE
  1558.                 tarinfo = self.proc_member(tarinfo)
  1559.             except ValueError:
  1560.                 e = None
  1561.                 if self.ignore_zeros:
  1562.                     self._dbg(2, '0x%X: empty or invalid block: %s' % (self.offset, e))
  1563.                     self.offset += BLOCKSIZE
  1564.                     continue
  1565.                 elif self.offset == 0:
  1566.                     raise ReadError('empty, unreadable or compressed file: %s' % e)
  1567.                 
  1568.                 return None
  1569.  
  1570.             break
  1571.         if tarinfo.isreg() and tarinfo.name.endswith('/'):
  1572.             tarinfo.type = DIRTYPE
  1573.         
  1574.         if tarinfo.isdir() and not tarinfo.name.endswith('/'):
  1575.             tarinfo.name += '/'
  1576.         
  1577.         self.members.append(tarinfo)
  1578.         return tarinfo
  1579.  
  1580.     
  1581.     def proc_member(self, tarinfo):
  1582.         if tarinfo.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
  1583.             return self.proc_gnulong(tarinfo)
  1584.         elif tarinfo.type == GNUTYPE_SPARSE:
  1585.             return self.proc_sparse(tarinfo)
  1586.         else:
  1587.             return self.proc_builtin(tarinfo)
  1588.  
  1589.     
  1590.     def proc_builtin(self, tarinfo):
  1591.         tarinfo.offset_data = self.offset
  1592.         if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES:
  1593.             self.offset += self._block(tarinfo.size)
  1594.         
  1595.         return tarinfo
  1596.  
  1597.     
  1598.     def proc_gnulong(self, tarinfo):
  1599.         buf = ''
  1600.         count = tarinfo.size
  1601.         while count > 0:
  1602.             block = self.fileobj.read(BLOCKSIZE)
  1603.             buf += block
  1604.             self.offset += BLOCKSIZE
  1605.             count -= BLOCKSIZE
  1606.             continue
  1607.             self
  1608.         b = self.fileobj.read(BLOCKSIZE)
  1609.         t = TarInfo.frombuf(b)
  1610.         t.offset = self.offset
  1611.         self.offset += BLOCKSIZE
  1612.         next = self.proc_member(t)
  1613.         next.offset = tarinfo.offset
  1614.         if tarinfo.type == GNUTYPE_LONGNAME:
  1615.             next.name = nts(buf)
  1616.         elif tarinfo.type == GNUTYPE_LONGLINK:
  1617.             next.linkname = nts(buf)
  1618.         
  1619.         return next
  1620.  
  1621.     
  1622.     def proc_sparse(self, tarinfo):
  1623.         buf = tarinfo.buf
  1624.         sp = _ringbuffer()
  1625.         pos = 386
  1626.         lastpos = 0x0L
  1627.         realpos = 0x0L
  1628.         for i in xrange(4):
  1629.             
  1630.             try:
  1631.                 offset = nti(buf[pos:pos + 12])
  1632.                 numbytes = nti(buf[pos + 12:pos + 24])
  1633.             except ValueError:
  1634.                 break
  1635.  
  1636.             if offset > lastpos:
  1637.                 sp.append(_hole(lastpos, offset - lastpos))
  1638.             
  1639.             sp.append(_data(offset, numbytes, realpos))
  1640.             realpos += numbytes
  1641.             lastpos = offset + numbytes
  1642.             pos += 24
  1643.         
  1644.         isextended = ord(buf[482])
  1645.         origsize = nti(buf[483:495])
  1646.         while isextended == 1:
  1647.             buf = self.fileobj.read(BLOCKSIZE)
  1648.             self.offset += BLOCKSIZE
  1649.             pos = 0
  1650.             for i in xrange(21):
  1651.                 
  1652.                 try:
  1653.                     offset = nti(buf[pos:pos + 12])
  1654.                     numbytes = nti(buf[pos + 12:pos + 24])
  1655.                 except ValueError:
  1656.                     self
  1657.                     self
  1658.                     break
  1659.                 except:
  1660.                     self
  1661.  
  1662.                 if offset > lastpos:
  1663.                     sp.append(_hole(lastpos, offset - lastpos))
  1664.                 
  1665.                 sp.append(_data(offset, numbytes, realpos))
  1666.                 realpos += numbytes
  1667.                 lastpos = offset + numbytes
  1668.                 pos += 24
  1669.             
  1670.             isextended = ord(buf[504])
  1671.         if lastpos < origsize:
  1672.             sp.append(_hole(lastpos, origsize - lastpos))
  1673.         
  1674.         tarinfo.sparse = sp
  1675.         tarinfo.offset_data = self.offset
  1676.         self.offset += self._block(tarinfo.size)
  1677.         tarinfo.size = origsize
  1678.         return tarinfo
  1679.  
  1680.     
  1681.     def _block(self, count):
  1682.         (blocks, remainder) = divmod(count, BLOCKSIZE)
  1683.         if remainder:
  1684.             blocks += 1
  1685.         
  1686.         return blocks * BLOCKSIZE
  1687.  
  1688.     
  1689.     def _getmember(self, name, tarinfo = None):
  1690.         members = self.getmembers()
  1691.         if tarinfo is None:
  1692.             end = len(members)
  1693.         else:
  1694.             end = members.index(tarinfo)
  1695.         for i in xrange(end - 1, -1, -1):
  1696.             if name == members[i].name:
  1697.                 return members[i]
  1698.                 continue
  1699.         
  1700.  
  1701.     
  1702.     def _load(self):
  1703.         while True:
  1704.             tarinfo = self.next()
  1705.             if tarinfo is None:
  1706.                 break
  1707.                 continue
  1708.         self._loaded = True
  1709.  
  1710.     
  1711.     def _check(self, mode = None):
  1712.         if self.closed:
  1713.             raise IOError('%s is closed' % self.__class__.__name__)
  1714.         
  1715.         if mode is not None and self._mode not in mode:
  1716.             raise IOError('bad operation for mode %r' % self._mode)
  1717.         
  1718.  
  1719.     
  1720.     def __iter__(self):
  1721.         if self._loaded:
  1722.             return iter(self.members)
  1723.         else:
  1724.             return TarIter(self)
  1725.  
  1726.     
  1727.     def _dbg(self, level, msg):
  1728.         if level <= self.debug:
  1729.             print >>sys.stderr, msg
  1730.         
  1731.  
  1732.  
  1733.  
  1734. class TarIter:
  1735.     
  1736.     def __init__(self, tarfile):
  1737.         self.tarfile = tarfile
  1738.         self.index = 0
  1739.  
  1740.     
  1741.     def __iter__(self):
  1742.         return self
  1743.  
  1744.     
  1745.     def next(self):
  1746.         if not self.tarfile._loaded:
  1747.             tarinfo = self.tarfile.next()
  1748.             if not tarinfo:
  1749.                 self.tarfile._loaded = True
  1750.                 raise StopIteration
  1751.             
  1752.         else:
  1753.             
  1754.             try:
  1755.                 tarinfo = self.tarfile.members[self.index]
  1756.             except IndexError:
  1757.                 raise StopIteration
  1758.  
  1759.         self.index += 1
  1760.         return tarinfo
  1761.  
  1762.  
  1763.  
  1764. class _section:
  1765.     
  1766.     def __init__(self, offset, size):
  1767.         self.offset = offset
  1768.         self.size = size
  1769.  
  1770.     
  1771.     def __contains__(self, offset):
  1772.         return None if offset <= offset else offset < self.offset + self.size
  1773.  
  1774.  
  1775.  
  1776. class _data(_section):
  1777.     
  1778.     def __init__(self, offset, size, realpos):
  1779.         _section.__init__(self, offset, size)
  1780.         self.realpos = realpos
  1781.  
  1782.  
  1783.  
  1784. class _hole(_section):
  1785.     pass
  1786.  
  1787.  
  1788. class _ringbuffer(list):
  1789.     
  1790.     def __init__(self):
  1791.         self.idx = 0
  1792.  
  1793.     
  1794.     def find(self, offset):
  1795.         idx = self.idx
  1796.         while True:
  1797.             item = self[idx]
  1798.             if offset in item:
  1799.                 break
  1800.             
  1801.             idx += 1
  1802.             if idx == len(self):
  1803.                 idx = 0
  1804.             
  1805.             if idx == self.idx:
  1806.                 return None
  1807.                 continue
  1808.         self.idx = idx
  1809.         return item
  1810.  
  1811.  
  1812. TAR_PLAIN = 0
  1813. TAR_GZIPPED = 8
  1814.  
  1815. class TarFileCompat:
  1816.     
  1817.     def __init__(self, file, mode = 'r', compression = TAR_PLAIN):
  1818.         if compression == TAR_PLAIN:
  1819.             self.tarfile = TarFile.taropen(file, mode)
  1820.         elif compression == TAR_GZIPPED:
  1821.             self.tarfile = TarFile.gzopen(file, mode)
  1822.         else:
  1823.             raise ValueError('unknown compression constant')
  1824.         if mode[0:1] == 'r':
  1825.             members = self.tarfile.getmembers()
  1826.             for m in members:
  1827.                 m.filename = m.name
  1828.                 m.file_size = m.size
  1829.                 m.date_time = time.gmtime(m.mtime)[:6]
  1830.             
  1831.         
  1832.  
  1833.     
  1834.     def namelist(self):
  1835.         return map((lambda m: m.name), self.infolist())
  1836.  
  1837.     
  1838.     def infolist(self):
  1839.         return filter((lambda m: m.type in REGULAR_TYPES), self.tarfile.getmembers())
  1840.  
  1841.     
  1842.     def printdir(self):
  1843.         self.tarfile.list()
  1844.  
  1845.     
  1846.     def testzip(self):
  1847.         pass
  1848.  
  1849.     
  1850.     def getinfo(self, name):
  1851.         return self.tarfile.getmember(name)
  1852.  
  1853.     
  1854.     def read(self, name):
  1855.         return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
  1856.  
  1857.     
  1858.     def write(self, filename, arcname = None, compress_type = None):
  1859.         self.tarfile.add(filename, arcname)
  1860.  
  1861.     
  1862.     def writestr(self, zinfo, bytes):
  1863.         
  1864.         try:
  1865.             StringIO = StringIO
  1866.             import cStringIO
  1867.         except ImportError:
  1868.             StringIO = StringIO
  1869.             import StringIO
  1870.  
  1871.         import calendar as calendar
  1872.         zinfo.name = zinfo.filename
  1873.         zinfo.size = zinfo.file_size
  1874.         zinfo.mtime = calendar.timegm(zinfo.date_time)
  1875.         self.tarfile.addfile(zinfo, StringIO(bytes))
  1876.  
  1877.     
  1878.     def close(self):
  1879.         self.tarfile.close()
  1880.  
  1881.  
  1882.  
  1883. def is_tarfile(name):
  1884.     
  1885.     try:
  1886.         t = open(name)
  1887.         t.close()
  1888.         return True
  1889.     except TarError:
  1890.         return False
  1891.  
  1892.  
  1893. open = TarFile.open
  1894.